package org.example.meetingsystem.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.example.meetingsystem.entity.MeetingRoom;
import org.example.meetingsystem.enums.RoomStatus;
import org.example.meetingsystem.mapper.MeetingRoomMapper;
import org.example.meetingsystem.service.MeetingRoomService;
import org.example.meetingsystem.util.BusinessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 会议室服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MeetingRoomServiceImpl implements MeetingRoomService {

    private final MeetingRoomMapper meetingRoomMapper;

    @Override
    public List<MeetingRoom> getAvailableRooms(Integer capacity, Boolean needProjector,
                                               Boolean needAudio, Boolean needNetwork) {
        try {
            List<MeetingRoom> rooms = meetingRoomMapper.selectAvailableRooms(
                    capacity, needProjector, needAudio, needNetwork);

            log.info("查询可用会议室，条件：容量>={}, 投影仪={}, 音响={}, 网络={}, 结果数量={}",
                    capacity, needProjector, needAudio, needNetwork, rooms.size());

            return rooms;
        } catch (Exception e) {
            log.error("查询可用会议室失败", e);
            throw new BusinessException("查询可用会议室失败");
        }
    }

    @Override
    public Page<MeetingRoom> getAllRooms(Page<MeetingRoom> page) {
        try {
            QueryWrapper<MeetingRoom> queryWrapper = new QueryWrapper<>();
            queryWrapper.orderByAsc("name");

            Page<MeetingRoom> result = meetingRoomMapper.selectPage(page, queryWrapper);

            log.info("分页查询会议室，页码：{}, 每页数量：{}, 总数：{}",
                    page.getCurrent(), page.getSize(), result.getTotal());

            return result;
        } catch (Exception e) {
            log.error("分页查询会议室失败", e);
            throw new BusinessException("查询会议室列表失败");
        }
    }

    @Override
    @Transactional
    public boolean addMeetingRoom(MeetingRoom meetingRoom) {
        try {
            // 验证必填字段
            validateMeetingRoom(meetingRoom, true);

            // 检查名称是否重复
            if (existsByName(meetingRoom.getName(), null)) {
                throw new BusinessException("会议室名称已存在");
            }

            // 设置默认状态和时间
            meetingRoom.setStatus(RoomStatus.AVAILABLE);
            meetingRoom.setCreatedAt(LocalDateTime.now());
            meetingRoom.setUpdatedAt(LocalDateTime.now());

            int result = meetingRoomMapper.insert(meetingRoom);

            if (result > 0) {
                log.info("添加会议室成功：{}", meetingRoom.getName());
                return true;
            } else {
                throw new BusinessException("添加会议室失败");
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("添加会议室失败", e);
            throw new BusinessException("添加会议室失败");
        }
    }

    @Override
    @Transactional
    public boolean updateMeetingRoom(Long id, MeetingRoom meetingRoom) {
        try {
            // 检查会议室是否存在
            if (!existsById(id)) {
                throw new BusinessException("会议室不存在");
            }

            // 验证必填字段
            validateMeetingRoom(meetingRoom, false);

            // 检查名称是否重复（排除自己）
            if (StringUtils.isNotBlank(meetingRoom.getName()) &&
                    existsByName(meetingRoom.getName(), id)) {
                throw new BusinessException("会议室名称已存在");
            }

            meetingRoom.setId(id);
            meetingRoom.setUpdatedAt(LocalDateTime.now());

            int result = meetingRoomMapper.updateById(meetingRoom);

            if (result > 0) {
                log.info("更新会议室成功，ID：{}", id);
                return true;
            } else {
                throw new BusinessException("更新会议室失败");
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新会议室失败，ID：{}", id, e);
            throw new BusinessException("更新会议室失败");
        }
    }

    @Override
    @Transactional
    public boolean deleteMeetingRoom(Long id) {
        try {
            // 检查会议室是否存在
            if (!existsById(id)) {
                throw new BusinessException("会议室不存在");
            }

            // 检查是否有正在进行或未来的预约
            // 使用现有的 checkRoomAvailability 方法来间接检查
            // 如果当前时间到未来很长时间内都有预约，则不允许删除
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime futureTime = now.plusYears(10); // 检查未来10年

            int activeReservations = meetingRoomMapper.checkRoomAvailability(id, now, futureTime);
            if (activeReservations > 0) {
                throw new BusinessException("该会议室有正在进行或未来的预约，无法删除");
            }

            int result = meetingRoomMapper.deleteById(id);

            if (result > 0) {
                log.info("删除会议室成功，ID：{}", id);
                return true;
            } else {
                throw new BusinessException("删除会议室失败");
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("删除会议室失败，ID：{}", id, e);
            throw new BusinessException("删除会议室失败");
        }
    }

    @Override
    public List<MeetingRoom> getAllRoomStatus() {
        try {
            QueryWrapper<MeetingRoom> queryWrapper = new QueryWrapper<>();
            queryWrapper.orderByAsc("name");

            List<MeetingRoom> rooms = meetingRoomMapper.selectList(queryWrapper);

            log.info("查询所有会议室状态，数量：{}", rooms.size());

            return rooms;
        } catch (Exception e) {
            log.error("查询会议室状态失败", e);
            throw new BusinessException("查询会议室状态失败");
        }
    }

    @Override
    @Transactional
    public boolean updateRoomStatus(Long id, RoomStatus status) {
        try {
            // 检查会议室是否存在
            if (!existsById(id)) {
                throw new BusinessException("会议室不存在");
            }

            // 验证状态参数
            if (status == null) {
                throw new BusinessException("会议室状态不能为空");
            }

            MeetingRoom room = new MeetingRoom();
            room.setId(id);
            room.setStatus(status);
            room.setUpdatedAt(LocalDateTime.now());

            int result = meetingRoomMapper.updateById(room);

            if (result > 0) {
                log.info("更新会议室状态成功，ID：{}, 新状态：{}", id, status);
                return true;
            } else {
                throw new BusinessException("更新会议室状态失败");
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新会议室状态失败，ID：{}, 状态：{}", id, status, e);
            throw new BusinessException("更新会议室状态失败");
        }
    }

    @Override
    public MeetingRoom getRoomById(Long id) {
        try {
            if (id == null) {
                return null;
            }
            return meetingRoomMapper.selectById(id);
        } catch (Exception e) {
            log.error("根据ID查询会议室失败，ID：{}", id, e);
            return null;
        }
    }

    @Override
    public boolean existsById(Long id) {
        if (id == null) {
            return false;
        }
        return meetingRoomMapper.selectById(id) != null;
    }

    @Override
    public boolean existsByName(String roomName, Long excludeId) {
        if (StringUtils.isBlank(roomName)) {
            return false;
        }

        QueryWrapper<MeetingRoom> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", roomName);

        if (excludeId != null) {
            queryWrapper.ne("id", excludeId);
        }

        return meetingRoomMapper.selectCount(queryWrapper) > 0;
    }

    @Override
    public boolean isRoomAvailable(Long roomId, LocalDateTime startTime, LocalDateTime endTime) {
        try {
            if (roomId == null || startTime == null || endTime == null) {
                return false;
            }

            // 检查会议室是否存在且可用
            MeetingRoom room = getRoomById(roomId);
            if (room == null || !RoomStatus.AVAILABLE.equals(room.getStatus())) {
                return false;
            }

            // 使用 MeetingRoomMapper 的 checkRoomAvailability 方法检查时间段冲突
            int conflictCount = meetingRoomMapper.checkRoomAvailability(roomId, startTime, endTime);
            return conflictCount == 0;
        } catch (Exception e) {
            log.error("检查会议室可用性失败，roomId：{}", roomId, e);
            return false;
        }
    }

    @Override
    public long countByStatus(RoomStatus status) {
        try {
            QueryWrapper<MeetingRoom> queryWrapper = new QueryWrapper<>();
            if (status != null) {
                queryWrapper.eq("status", status);
            }
            return meetingRoomMapper.selectCount(queryWrapper);
        } catch (Exception e) {
            log.error("统计会议室数量失败，状态：{}", status, e);
            return 0;
        }
    }

    @Override
    @Transactional
    public int batchUpdateStatus(List<Long> roomIds, RoomStatus status) {
        try {
            if (roomIds == null || roomIds.isEmpty() || status == null) {
                return 0;
            }

            int successCount = 0;
            for (Long roomId : roomIds) {
                if (updateRoomStatus(roomId, status)) {
                    successCount++;
                }
            }

            log.info("批量更新会议室状态完成，总数：{}, 成功：{}, 状态：{}",
                    roomIds.size(), successCount, status);

            return successCount;
        } catch (Exception e) {
            log.error("批量更新会议室状态失败", e);
            throw new BusinessException("批量更新会议室状态失败");
        }
    }

    /**
     * 验证会议室信息
     */
    private void validateMeetingRoom(MeetingRoom meetingRoom, boolean isAdd) {
        if (meetingRoom == null) {
            throw new BusinessException("会议室信息不能为空");
        }

        if (isAdd || StringUtils.isNotBlank(meetingRoom.getName())) {
            if (StringUtils.isBlank(meetingRoom.getName())) {
                throw new BusinessException("会议室名称不能为空");
            }
            if (meetingRoom.getName().length() > 50) {
                throw new BusinessException("会议室名称长度不能超过50个字符");
            }
        }

        if (meetingRoom.getCapacity() != null && meetingRoom.getCapacity() <= 0) {
            throw new BusinessException("会议室容量必须大于0");
        }

        if (meetingRoom.getDescription() != null && meetingRoom.getDescription().length() > 500) {
            throw new BusinessException("会议室描述长度不能超过500个字符");
        }
    }
}